import 'package:flutter/material.dart';
import 'package:x3_component_core/components/state_components/base_empty_component.dart';

enum OperableControllerState { insert, remove }

/// 开启动画key
class OperableController<T> extends ChangeNotifier {
  /// 全局动画key
  final GlobalKey<SliverAnimatedListState> animationKey = GlobalKey<SliverAnimatedListState>();

  /// 数据源
  List<T> dataSource = [];

  /// 增加的 数据
  T _data;

  /// 移除的 index
  int _index;

  /// 状态
  OperableControllerState _state;

  /// 移除
  void remove({@required int index}) {
    this._index = index;
    this._state = OperableControllerState.remove;
    notifyListeners();
  }

  /// 增加
  void insert({@required T item}) {
    this._data = item;
    this._state = OperableControllerState.insert;
    notifyListeners();
  }
}

/// 可操作列
class BaseOperableList<T> extends StatefulWidget {
  final List<Widget> header;
  final OperableController operableController;
  final Widget Function(T, int) buildItem;

  BaseOperableList({Key key, this.header, @required this.operableController, @required this.buildItem}) : super(key: key);

  @override
  _BaseOperableListState createState() => _BaseOperableListState<T>();
}

class _BaseOperableListState<T> extends State<BaseOperableList> {
  GlobalKey<SliverAnimatedListState> get _animationKey => widget.operableController.animationKey;
  List get _dataSource => widget.operableController.dataSource;
  @override
  void initState() {
    /// 动画监听事件
    // ignore: invalid_use_of_protected_member
    if (widget.operableController.hasListeners == false) {
      widget.operableController.addListener(() {
        switch (widget.operableController._state) {
          case OperableControllerState.insert:
            insert();
            break;
          case OperableControllerState.remove:
            remove();
            if (_dataSource.isEmpty) setState(() => {});
            break;
        }
      });
    }
    super.initState();
  }

  /// 增加
  void insert() {
    var data = widget.operableController._data;
    bool isContains = widget.operableController.dataSource.map((e) => e.toString()).toList().contains(data.toString());
    if (!isContains) {
      widget.operableController.dataSource.insert(0, data);
      _animationKey.currentState?.insertItem(0);
    }
  }

  /// 移除
  void remove() {
    int _index = widget.operableController._index;
    T data = widget.operableController.dataSource.elementAt(_index);
    _animationKey.currentState.removeItem(_index, (context, animation) {
      Widget child = _buildAnimationItem(data, _index, animation);
      return child;
    });
    widget.operableController.dataSource.removeAt(_index);
  }

  @override
  Widget build(BuildContext context) {
    return CustomScrollView(
      physics: NeverScrollableScrollPhysics(),
      shrinkWrap: true,
      slivers: [
        SliverToBoxAdapter(child: Column(children: widget.header ?? [])),
        _buildBodyContent(),
      ],
    );
  }

  Widget _buildBodyContent() {
    if (this._dataSource is List && this._dataSource.length > 0) {
      return SliverSafeArea(
        sliver: SliverAnimatedList(
          key: _animationKey,
          initialItemCount: widget.operableController.dataSource.length,
          itemBuilder: (BuildContext context, int index, Animation<double> animation) {
            return _buildAnimationItem(this._dataSource[index], index, animation);
          },
        ),
      );
    }
    return SliverToBoxAdapter(child: BaseEmptyComponent());
  }

  /// 动画效果1
  Widget _buildAnimationItem(T item, int index, Animation<double> animation) {
    return SizeTransition(
      key: Key(index.toString()),
      sizeFactor: animation,
      child: widget.buildItem(item, index),
    );
  }

  /// 动画效果2
  Widget _buildAnimationItemSlide(T item, int index, Animation animation) {
    return ClipRRect(
      child: SlideTransition(
        key: Key(index.toString()),
        position: animation.drive(CurveTween(curve: Curves.easeIn)).drive(
              Tween<Offset>(begin: Offset(1, 0), end: Offset(0, 0)),
            ),
        child: widget.buildItem(item, index),
      ),
    );
  }
}
